package top.eggcode.base;

import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import top.eggcode.common.exception.ApplicationException;
import top.eggcode.common.lang.BeanUnit;

import javax.annotation.Resource;
import java.beans.IntrospectionException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Optional;

/**
 * Title: 基础服务实现
 * Description: TODO
 * Date: 2021/3/29 12:47
 *
 * @author JiaQi Ding
 * @version 1.0
 */
@Transactional(rollbackFor = Exception.class)
public abstract class BaseServiceImpl<T> implements BaseService<T> {

    /**
     * 实体类的Class对象
     */
    private final Class<T> clazz;
    @Resource
    private EntityStore repository;

    @SuppressWarnings("unchecked")
    public BaseServiceImpl() {
        // 获取实体类的class
        ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
        this.clazz = ((Class<T>) type.getActualTypeArguments()[0]);
    }

    @Override
    public boolean add(T entity) {
        repository.add(entity);
        return true;
    }

    @Override
    public void delete(T entity) {
        repository.delete(entity);
    }

    @Override
    public void deleteById(String id) {
        get(id).ifPresent(this::delete);
    }


    protected String getPrimeKey(Object entity) {
        String entityId = "";
        try {
            entityId = (String) BeanUnit.getAttributeValue("id", entity);
        } catch (InvocationTargetException | IllegalAccessException | IntrospectionException e) {
            e.printStackTrace();
            throw new ApplicationException(e, "无法获取实体的id属性。");
        }
        return entityId;
    }

    @Override
    public void update(T entity) {
        // 获取完整实体
        get(this.getPrimeKey(entity)).ifPresent(aliveEntity -> {
            // 用参数的非空属性覆盖数据库实体的属性
            BeanUnit.rewrite(aliveEntity, entity);
            repository.update(aliveEntity);
        });

    }

    @Override
    public void updateFull(T entity) {
        repository.update(entity);
    }

    @Override
    public void put(T entity) {

        // 如果id存在
        if (StringUtils.isNotBlank(this.getPrimeKey(entity))) {
            // 查询数据库记录
            Optional<T> box = repository.get(clazz, this.getPrimeKey(entity));
            if (box.isPresent()) {
                this.update(entity);
            } else {
                this.add(entity);
            }
        } else {
            throw new ApplicationException("实体的属性 id 为空");
        }


    }

    @Override
    public List<T> find() {
        return repository.selectAll(clazz);
    }

    @Override
    public Optional<T> get(String id) {
        return repository.get(clazz, id);
    }

    @Override
    public void batchPut(List<T> entityList) {
        entityList.forEach(this::put);
    }

    @Override
    public void batchAdd(List<T> entityList) {
        entityList.forEach(this::add);
    }

    @Override
    public void flush() {
        repository.flush();
    }

    @Override
    public void refresh(T entity) {
        repository.refresh(entity);
    }

    /**
     * 必须有一条
     *
     * @param entityList 数据列表
     * @return 对象
     */
    protected T requireOne(List<T> entityList) {
        if (entityList.size() > 1) {
            throw new ApplicationException("数据疑似重复。");
        } else if (entityList.size() == 0) {
            throw new ApplicationException("数据为空。");
        } else {
            return entityList.get(0);
        }
    }

    /**
     * 最多有一条
     *
     * @param entityList 数据列表
     * @return 对象
     */
    protected T mostOne(List<T> entityList) {
        if (entityList.size() > 1) {
            throw new ApplicationException("数据疑似重复。");
        } else if (entityList.size() == 0) {
            return null;
        } else {
            return entityList.get(0);
        }
    }
}
